package logic

import (
	"context"
	"fmt"
	"git.xiaotuo.co/micro/oss/config"
	log "github.com/sirupsen/logrus"
	"io"
	"net/http"
	"strings"
	"time"
)

type CheckLogic struct {
	client   *http.Client
	interval time.Duration
	urls     []config.UrlConfig
}

func newCheckLogic(opts ...Option) CheckLogic {
	options := &Options{}
	for _, o := range opts {
		o(options)
	}

	timeout := time.Second * 3
	if options.config.Timeout > 0 {
		timeout = time.Second * time.Duration(options.config.Timeout)
	}

	interval := time.Second * 15
	if options.config.Interval > 0 {
		interval = time.Second * time.Duration(options.config.Interval)
	}

	return CheckLogic{
		client:   &http.Client{Timeout: timeout},
		interval: interval,
		urls:     options.config.Urls,
	}
}

func (lgc CheckLogic) Run(ctx context.Context) {
	for _, item := range lgc.urls {
		go lgc.check(ctx, item)
	}
}

func (lgc CheckLogic) check(ctx context.Context, item config.UrlConfig) {
	method := strings.ToUpper(item.Method)
	for {
		select {
		case <-ctx.Done():
			log.Debugf("check_quit: %s", item.Url)
			return
		default:
			latency, err := lgc.http(method, item.Url)
			if err != nil {
				log.WithFields(log.Fields{"method": method, "url": item.Url, "latency": latency}).Error(err)
			} else {
				log.WithFields(log.Fields{"method": method, "url": item.Url, "latency": latency}).Info()
			}
			time.Sleep(lgc.interval)
		}
	}
}

func (lgc CheckLogic) http(method, reqUrl string) (int64, error) {
	startTime := time.Now()
	request, err := http.NewRequest(method, reqUrl, nil)
	if err != nil {
		return 0, err
	}
	request.Header.Set("User-Agent", "check")
	resp, err := lgc.client.Do(request)
	if err != nil {
		latency := time.Now().UnixMilli() - startTime.UnixMilli()
		return latency, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		latency := time.Now().UnixMilli() - startTime.UnixMilli()
		return latency, fmt.Errorf("%s", resp.Status)
	}
	_, err = io.ReadAll(resp.Body)
	if err != nil {
		return 0, err
	}
	latency := time.Now().UnixMilli() - startTime.UnixMilli()
	return latency, nil
}
